package com.x.core.wrapper.mybatisplus;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.x.core.domain.BaseQuery;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

public interface CrudMapper<T, Q extends BaseQuery> extends BaseMapper<T> {

    default List<T> list(Q q){
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        buildQuery(q, queryWrapper);
        return selectList(queryWrapper);
    }

    default T get(Q q){
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        buildQuery(q, queryWrapper);
        return selectOne(queryWrapper);
    }

    void buildQuery(Q q, LambdaQueryWrapper<T> queryWrapper);

    default boolean retBool(Integer result) {
        return SqlHelper.retBool(result);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdate(T entity) {
        return saveOrUpdate(entity, false);
    }
    @Transactional(
            rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdate(T entity, Boolean checkDbExist) {
        if (null == entity) {
            return false;
        } else {
            Class<?> cls = entity.getClass();
            TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
            String keyProperty = tableInfo.getKeyProperty();
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
            Object idVal = ReflectUtil.getFieldValue(entity, tableInfo.getKeyProperty());
            if (StringUtils.checkValNull(idVal) || (checkDbExist && Objects.isNull(this.selectById((Serializable)idVal)))){
               return retBool(insert(entity));
            }
            return retBool(this.updateById(entity));
        }
    }

}
